package com.xdjd.mobile.business.service;

import com.gitee.easyopen.exception.ApiException;
import com.xdjd.mobile.business.constant.*;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityChallengeRecordDetailPoService;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityChallengeRecordPoService;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityClockDetailPoService;
import com.xdjd.mobile.business.dao.daoservice.activity.ActivityUserClockPoService;
import com.xdjd.mobile.business.dao.daoservice.member.MemberUserPoService;
import com.xdjd.mobile.business.dao.daoservice.member.MemberUserStepPoService;
import com.xdjd.mobile.business.dao.daoservice.member.MemberUserWalletPoService;
import com.xdjd.mobile.business.dao.mapper.activity.ActivityChallengeRecordDetailPoDao;
import com.xdjd.mobile.business.dao.mapper.activity.ActivityChallengeRecordPoDao;
import com.xdjd.mobile.business.entity.model.activity.ActivityChallengeRecordDetailPo;
import com.xdjd.mobile.business.entity.model.activity.ActivityChallengeRecordPo;
import com.xdjd.mobile.business.entity.model.activity.ActivityClockDetailPo;
import com.xdjd.mobile.business.entity.model.activity.ActivityUserClockPo;
import com.xdjd.mobile.business.entity.model.member.MemberUserPo;
import com.xdjd.mobile.business.entity.model.member.MemberUserStepPo;
import com.xdjd.mobile.business.entity.model.member.MemberUserWalletPo;
import com.xdjd.mobile.business.entity.param.BasePageParam;
import com.xdjd.mobile.business.entity.param.challenge.BaseChallengeParam;
import com.xdjd.mobile.business.entity.result.challenge.*;
import com.xdjd.mobile.business.entity.result.challenge.ChallengeRecordResult;
import com.xdjd.mobile.business.entity.result.challenge.ChallengeVo;
import com.xdjd.mobile.business.entity.result.challenge.RandomChallengeResult;
import com.xdjd.mobile.business.entity.vo.ChallengeMyPkResult;
import com.xdjd.mobile.business.entity.vo.ChallengeMyPkVO;
import com.xdjd.mobile.business.entity.vo.ChallengeRoomInfoVO;
import com.xdjd.mobile.business.util.DateUtil;
import com.xdjd.mobile.business.util.UUIDUtil;
import com.xdjd.mobile.business.util.UUIDUtils;
import net.oschina.durcframework.easymybatis.PageInfo;
import net.oschina.durcframework.easymybatis.query.Query;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by Administrator on 2019/1/9 0009.
 */
@Service
public class ChallengeService {

    @Autowired
    private MemberUserStepPoService memberUserStepPoService;
    @Autowired
    private ActivityChallengeRecordPoService activityChallengeRecordPoService;
    @Autowired
    private ActivityChallengeRecordDetailPoService activityChallengeRecordDetailPoService;
    @Autowired
    private ActivityUserClockPoService activityUserClockPoService;
    @Autowired
    private ActivityClockDetailPoService activityClockDetailPoService;
    @Autowired
    private MemberUserPoService memberUserPoService;
    @Autowired
    private MemberUserWalletPoService memberUserWalletPoService;
    @Autowired
    private ActivityChallengeRecordPoDao activityChallengeRecordPoDao;
    @Autowired
    private ActivityChallengeRecordDetailPoDao activityChallengeRecordDetailPoDao;

    @Transactional
    public void updateStep(Long stepNumber, Long memberId) {
        memberUserStepPoService.updateStepNumber(memberId, stepNumber);
        if (stepNumber.longValue() >= Constant.CHANCE_STEP.longValue()) {
            memberUserStepPoService.addChanceCountLock(memberId);
            activityChallengeRecordDetailPoService.updateTodayStepByMemberId(memberId, stepNumber);
            ActivityChallengeRecordPo recordPo = activityChallengeRecordPoService.findTodayRecordByMemberId(memberId);
            if (recordPo == null) {
                recordPo = new ActivityChallengeRecordPo();
                recordPo.setMemberId(memberId);
                recordPo.setRecordNo("XD" + UUIDUtil.createOutTradeNo());
                recordPo.setChallengeCount(0);
                recordPo.setStepNumber(stepNumber);
                recordPo.setRecordDate(new Date());
                recordPo.setCompleteStatus(new Byte("0"));
                recordPo.setObtainCoin(0);
                activityChallengeRecordPoService.saveRecord(recordPo);
                ActivityChallengeRecordDetailPo detailPo = new ActivityChallengeRecordDetailPo();
                detailPo.setRecordNo(recordPo.getRecordNo());
                detailPo.setMemberId(memberId);
                detailPo.setStepNumber(stepNumber);
                detailPo.setRecordDate(new Date());
                detailPo.setIsOwn(IsOwnStatus.is_own.getCode().byteValue());
                detailPo.setObtainCoin(0);
                activityChallengeRecordDetailPoService.saveRecordDetail(detailPo);
            } else {
                activityChallengeRecordPoService.updateTodayStepByMemberId(memberId, stepNumber);
            }
        }
        ActivityUserClockPo userClockPo = activityUserClockPoService.findByMemberId(memberId);
        if (userClockPo != null) {
            ActivityClockDetailPo clockDetailPo = activityClockDetailPoService.findByClockNoAndDate(userClockPo.getClockNo(), DateUtil.getDate(new Date()));
            if (clockDetailPo == null) {
                if (userClockPo.getRemainDay().intValue() > 0) {
                    clockDetailPo = new ActivityClockDetailPo();
                    clockDetailPo.setMemberId(memberId);
                    clockDetailPo.setClockNo(userClockPo.getClockNo());
                    clockDetailPo.setTargetStepNumber(userClockPo.getDayStepNumber());
                    clockDetailPo.setTodayStepNumber(stepNumber);
                    clockDetailPo.setStatus(ClockCompleteTargetStatus.failure.getCode().byteValue());
                    clockDetailPo.setCompleteStatus(new Byte("0"));
                    if (stepNumber.longValue() >= userClockPo.getDayStepNumber().longValue()) {
                        clockDetailPo.setStatus(ClockCompleteTargetStatus.successful.getCode().byteValue());
                    }
                    clockDetailPo.setClockDate(new Date());
                    activityClockDetailPoService.saveClockDetail(clockDetailPo);
                    activityUserClockPoService.reduceRemainDay(userClockPo.getClockNo());
                }
            } else {
                clockDetailPo.setTodayStepNumber(stepNumber);
                if (stepNumber.longValue() >= clockDetailPo.getTargetStepNumber().longValue()) {
                    clockDetailPo.setStatus(ClockCompleteTargetStatus.successful.getCode().byteValue());
                }
                activityClockDetailPoService.updateClockDetail(clockDetailPo);
            }
        }
    }

    public RandomChallengeResult randomChallengeList(Long memberId, Integer count) {
        RandomChallengeResult result = new RandomChallengeResult();
        List<ActivityChallengeRecordPo> canChallengeList = activityChallengeRecordPoService.findCanChallengeList();
        List<ChallengeVo> list = new ArrayList<>();
        if (canChallengeList.size() > count.intValue()) {
            canChallengeList = this.randomList(canChallengeList, count, memberId);
        } else {
            canChallengeList = this.randomList(canChallengeList, canChallengeList.size(), memberId);
        }
        for (ActivityChallengeRecordPo recordPo : canChallengeList) {
            ChallengeVo vo = new ChallengeVo();
            MemberUserPo userPo = memberUserPoService.getMemberById(recordPo.getMemberId());
            vo.setRecordNo(recordPo.getRecordNo());
            vo.setLogo(userPo.getImage());
            list.add(vo);
        }
        result.setList(list);
        result.setMaxStepNumber(Constant.CHANCE_STEP);
        if (memberId != null) {
            ActivityChallengeRecordPo challengeRecordPo = activityChallengeRecordPoService.findTodayRecordByMemberId(memberId);
            MemberUserStepPo userStepPo = memberUserStepPoService.findStepByMemberId(memberId);
            MemberUserWalletPo userWalletPo = memberUserWalletPoService.findWalletByMemberId(memberId);
            result.setObtainCoin(userWalletPo.getObtainCoin());
            result.setStepNumber(userStepPo.getTodayStepNumber());
            Long ownChallengeCount = activityChallengeRecordDetailPoService.findOwnChallengeCount(memberId);
            result.setChallengeCount(ownChallengeCount.intValue());
            if (challengeRecordPo != null) {
                if (challengeRecordPo.getChallengeCount().intValue() > 0) {
                    result.setRecordNo(challengeRecordPo.getRecordNo());
                    result.setChallengePeople(challengeRecordPo.getChallengeCount());
                }
                ActivityChallengeRecordDetailPo ownChallengeRecordToday = activityChallengeRecordDetailPoService.findOwnChallengeRecordToday(memberId);
                if (ownChallengeRecordToday == null) {
                    result.setButtonStatus(new Byte("1"));
                } else {
                    if (ownChallengeRecordToday.getRanking() != null) {
                        result.setButtonStatus(new Byte("3"));
                    } else {
                        result.setButtonStatus(new Byte("2"));
                    }
                }
            }
        }
        return result;
    }

    private List<ActivityChallengeRecordPo> randomList(List<ActivityChallengeRecordPo> canChallengeList, Integer count, Long memberId) {
        List<ActivityChallengeRecordPo> newList = new ArrayList<>();
        Random random = new Random();
        int i = 0;
        while (true) {
            int target = random.nextInt(canChallengeList.size());
            if (memberId != null && canChallengeList.get(target).getMemberId().longValue() == memberId.longValue()) {
                if (canChallengeList.size() == 1) {
                    break;
                }
                continue;
            }
            newList.add(canChallengeList.get(target));
            canChallengeList.remove(target);
            i++;
            if (i >= count.intValue()) {
                break;
            }
        }
        return newList;
    }

    @Transactional
    public void challengeUser(Long memberId, String recordNo, Long stepNumber) {
        ActivityChallengeRecordPo challengeRecordPo = activityChallengeRecordPoService.findRecordByRecordNo(recordNo);
        if (challengeRecordPo.getMemberId().longValue() == memberId.longValue()) {
            throw new ApiException(ErrorCodeEnum.challenge_own.getDesc(), ErrorCodeEnum.challenge_own.getCode());
        }
        int chanceCount = memberUserStepPoService.reduceDefaultChanceCountLock(memberId);
        if (chanceCount == 0) {
            int count = memberUserStepPoService.reduceChanceCountLock(memberId);
            if (count == 0) {
                throw new ApiException(ErrorCodeEnum.challenge_count_finish.getDesc(), ErrorCodeEnum.challenge_count_finish.getCode());
            }
        }
        int i = activityChallengeRecordPoService.addChallengeCountLock(recordNo);
        if (i == 0) {
            throw new ApiException(ErrorCodeEnum.can_challenge_count_finish.getDesc(), ErrorCodeEnum.can_challenge_count_finish.getCode());
        }
        ActivityChallengeRecordDetailPo recordDetailPo = new ActivityChallengeRecordDetailPo();
        recordDetailPo.setRecordNo(recordNo);
        recordDetailPo.setMemberId(memberId);
        recordDetailPo.setStepNumber(stepNumber);
        recordDetailPo.setRecordDate(new Date());
        recordDetailPo.setIsOwn(IsOwnStatus.not_own.getCode().byteValue());
        recordDetailPo.setObtainCoin(0);
        activityChallengeRecordDetailPoService.saveRecordDetail(recordDetailPo);
    }

    public PageInfo<ChallengeRecordResult> getChallengeList(BasePageParam param, Long memberId) {
        PageInfo<ActivityChallengeRecordDetailPo> recordPage = activityChallengeRecordDetailPoService.getChallengeRecordList(memberId, param.getPageIndex(), param.getPageSize());
        PageInfo<ChallengeRecordResult> pageInfo = new PageInfo<>();
        List<ChallengeRecordResult> resultList = new ArrayList<>();
        List<ActivityChallengeRecordDetailPo> list = recordPage.getList();
        for (ActivityChallengeRecordDetailPo detailPo : list) {
            ChallengeRecordResult result = new ChallengeRecordResult();
            ActivityChallengeRecordPo record = activityChallengeRecordPoService.findRecordByRecordNo(detailPo.getRecordNo());
            MemberUserPo userPo = memberUserPoService.getMemberById(record.getMemberId());
            result.setLogo(userPo.getImage());
            result.setNickName(userPo.getNickName());
            result.setChallengeDate(DateUtil.getDate(detailPo.getRecordDate()));
            result.setStepNumber(detailPo.getStepNumber());
            result.setRecordNo(detailPo.getRecordNo());
            if (DateUtil.getDate(detailPo.getRecordDate()).equals(DateUtil.getDate(new Date()))) {
                result.setStatus(ClockAndChallengeResultStatus.ongoing.getCode().byteValue());
            } else if (detailPo.getStepNumber().longValue() >= record.getStepNumber().longValue()) {
                result.setStatus(ClockAndChallengeResultStatus.successful.getCode().byteValue());
            } else {
                result.setStatus(ClockAndChallengeResultStatus.failure.getCode().byteValue());
            }
            resultList.add(result);
        }
        pageInfo.setList(resultList);
        pageInfo.setPageIndex(recordPage.getPageIndex());
        pageInfo.setPageSize(recordPage.getPageSize());
        pageInfo.setTotal(recordPage.getTotal());
        return pageInfo;
    }

    public MyChallengeResult findMyChallenge(BaseChallengeParam param) {
        MyChallengeResult result = new MyChallengeResult();
        ActivityChallengeRecordPo recordPo = activityChallengeRecordPoService.findRecordByRecordNo(param.getRecordNo());
        MemberUserPo userPo = memberUserPoService.getMemberById(recordPo.getMemberId());
        result.setImage(userPo.getImage());
        result.setNickName(userPo.getNickName());
        result.setStepNumber(recordPo.getStepNumber());
        result.setChallengePeople(recordPo.getChallengeCount());
        List<ActivityChallengeRecordDetailPo> recordDetailPos = activityChallengeRecordDetailPoService.findChallengeMeByRecordNo(param.getRecordNo());
        int surpassCount = 0;
        List<ChallengeMeVo> list = new ArrayList<>();
        for (ActivityChallengeRecordDetailPo recordDetailPo : recordDetailPos) {
            ChallengeMeVo vo = new ChallengeMeVo();
            MemberUserPo member = memberUserPoService.getMemberById(recordDetailPo.getMemberId());
            vo.setImage(member.getImage());
            vo.setNickName(member.getNickName());
            vo.setSurpassStatus(new Byte("0"));
            vo.setStepNumber(recordDetailPo.getStepNumber());
            if (recordDetailPo.getStepNumber().longValue() > recordPo.getStepNumber().longValue()) {
                surpassCount++;
                vo.setSurpassStatus(new Byte("1"));
            }
            list.add(vo);
        }
        result.setSurpassCount(surpassCount);
        result.setList(list);
        if (surpassCount > 0) {
            result.setMarkWord("再接再厉！在努力一点点就能守擂成功了！");
        } else if (recordPo.getChallengeCount().intValue() > 0) {
            result.setMarkWord("恭喜你超过所有挑战者，继续坚持胜利属于你！");
        } else {
            result.setMarkWord("你还没有挑战者哦！");
        }
        return result;
    }

    public ChallengeRoomInfoVO challengeRoomInfo(Long curUserId, String recordNo) {
        String curDate = DateUtil.getDate(new Date());
        ActivityChallengeRecordPo activityChallengeRecordPo = getRecordNoByCurDateFromRoom(curUserId, recordNo, curDate);
        if (activityChallengeRecordPo == null) {
            throw new ApiException("暂时没有可挑战的选手", "-1");
        }
        if (activityChallengeRecordPo.getMemberId().longValue() == curUserId.longValue()) {
            throw new ApiException("不能挑战自己", "-1");
        }
        String recordNoRandom = activityChallengeRecordPo.getRecordNo();

        ChallengeRoomInfoVO challengeRoomInfoVO = new ChallengeRoomInfoVO();
        challengeRoomInfoVO.setChallengerImages(getChallengerImages(recordNoRandom));
        challengeRoomInfoVO.setChallengeCount(activityChallengeRecordPo.getChallengeCount());
        challengeRoomInfoVO.setRecordNo(recordNoRandom);
        challengeRoomInfoVO.setRoomerImage(getRoomerImage(activityChallengeRecordPo.getMemberId()));
        challengeRoomInfoVO.setObtainCoin(activityChallengeRecordPo.getChallengeCount());
        return challengeRoomInfoVO;
    }

    private String getRoomerImage(Long memberId) {
        MemberUserPo memberUserPo = memberUserPoService.getMemberById(memberId);
        if (memberUserPo == null) {
            throw new ApiException("擂主信息不存在", "-1");
        }
        return memberUserPo.getImage();
    }

    private ActivityChallengeRecordPo getRecordNoByCurDateFromRoom(Long curUserId, String recordNo, String curDate) {
        if (StringUtils.isNotBlank(recordNo)) {
            Query query = new Query().eq("record_no", recordNo);
            return activityChallengeRecordPoDao.getByExpression(query);
        }
        Query query = new Query().eq("record_date", curDate).notEq("member_id", curUserId);
        Long count = activityChallengeRecordPoDao.countTotal(query);
        if (count.longValue() == 0) {
            return null;
        }
        Integer start = new Random(count).nextInt();
        query = new Query().eq("record_date", curDate).notEq("member_id", curUserId).limit(start, 1);
        return activityChallengeRecordPoDao.getByExpression(query);

    }

    private List<String> getChallengerImages(String recordNo) {
        return activityChallengeRecordPoDao.getChallengerImages(recordNo);
    }


    public ChallengeMyPkResult challengeMyPk(Long id) {
        ActivityChallengeRecordDetailPo activityChallengeRecordPo = getChallengeMyPkRecordNo(id);
        if (activityChallengeRecordPo == null) {
            throw new ApiException("您当前没有PK信息", "-1");
        }
        String recordNo = activityChallengeRecordPo.getRecordNo();
        ChallengeMyPkResult challengeMyPkResult = activityChallengeRecordPoDao.challengeMyPk(id, recordNo);
        Long roomStep = challengeMyPkResult.getRoomerStep() == null ? 0 : challengeMyPkResult.getRoomerStep();
        List<ChallengeMyPkVO> challengeMyPkVOS = activityChallengeRecordPoDao.getChallengeMyPkVOS(recordNo, roomStep);
        Integer curChallengeCount = CollectionUtils.isEmpty(challengeMyPkVOS) ? 0 : challengeMyPkVOS.size();
        challengeMyPkResult.setCurChallengeCount(curChallengeCount);
        challengeMyPkResult.setChallengeMyPkVOList(challengeMyPkVOS);
        return challengeMyPkResult;


    }

    private ActivityChallengeRecordDetailPo getChallengeMyPkRecordNo(Long id) {
        Query query = new Query().eq("member_id", id).eq("record_date", DateUtil.getDate(new Date()));
        return activityChallengeRecordDetailPoDao.getByExpression(query);
    }

    public PageInfo<BeChallengeRecordResult> getBeChallengeList(BasePageParam param, Long memberId) {
        PageInfo<ActivityChallengeRecordPo> beChallengeRecord = activityChallengeRecordPoService.getBeChallengeRecord(memberId, param.getPageIndex(), param.getPageSize());
        PageInfo<BeChallengeRecordResult> pageInfo = new PageInfo<>();
        List<BeChallengeRecordResult> resultList = new ArrayList<>();
        List<ActivityChallengeRecordPo> list = beChallengeRecord.getList();
        for (ActivityChallengeRecordPo recordPo : list) {
            BeChallengeRecordResult result = new BeChallengeRecordResult();
            //排除今天的记录
            if (DateUtil.getDate(recordPo.getRecordDate()).equals(DateUtil.getDate(new Date()))) {
                continue;
            }
            result.setRecordNo(recordPo.getRecordNo());
            result.setStepNumber(recordPo.getStepNumber());
            result.setObtianCoin(recordPo.getObtainCoin());
            result.setRecordDate(DateUtil.getDate(recordPo.getRecordDate()));
            //此次记录成功失败的状态和对应的人数
            if (recordPo.getRanking() == null) {
                result.setStatus(ClockAndChallengeResultStatus.ongoing.getCode().byteValue());
                result.setPeopleCount(0);
            } else if (recordPo.getRanking() == 1) {
                result.setStatus(ClockAndChallengeResultStatus.successful.getCode().byteValue());
                result.setPeopleCount(recordPo.getChallengeCount());
            } else {
                result.setStatus(ClockAndChallengeResultStatus.failure.getCode().byteValue());
                result.setPeopleCount(recordPo.getRanking() - 1);
            }
            resultList.add(result);
        }
        pageInfo.setList(resultList);
        pageInfo.setPageIndex(beChallengeRecord.getPageIndex());
        pageInfo.setTotal(beChallengeRecord.getTotal());
        pageInfo.setPageSize(beChallengeRecord.getPageSize());
        return pageInfo;
    }

    public PageInfo<ChallengeRecordsResult> getChallengeRecordsList(BasePageParam param, Long memberId) {
        PageInfo<ActivityChallengeRecordDetailPo> challengeRecordList = activityChallengeRecordDetailPoService.getChallengeRecordList(memberId, param.getPageIndex(), param.getPageSize());
        PageInfo<ChallengeRecordsResult> pageInfo = new PageInfo<>();
        List<ChallengeRecordsResult> resultList = new ArrayList<>();
        List<ActivityChallengeRecordDetailPo> list = challengeRecordList.getList();
        for (ActivityChallengeRecordDetailPo detailPo : list) {
            ChallengeRecordsResult result = new ChallengeRecordsResult();
            //排除今天记录
            if (DateUtil.getDate(detailPo.getRecordDate()).equals(DateUtil.getDate(new Date()))) {
                continue;
            }
            result.setRecordNo(detailPo.getRecordNo());
            result.setObtianCoin(detailPo.getObtainCoin());
            result.setRecordDate(DateUtil.getDate(detailPo.getRecordDate()));
            result.setStepNumber(detailPo.getStepNumber());
            //判断挑战状态 根据编号查找记录 通过步数比较输赢
            ActivityChallengeRecordPo recordByRecordNo = activityChallengeRecordPoService.findRecordByRecordNo(detailPo.getRecordNo());
            if (detailPo.getStepNumber().longValue() > recordByRecordNo.getStepNumber()) {
                result.setStatus(ClockAndChallengeResultStatus.successful.getCode().byteValue());
            } else if (detailPo.getStepNumber().longValue() == recordByRecordNo.getStepNumber() && detailPo.getModifyTime().getTime() < recordByRecordNo.getModifyTime().getTime()) {
                result.setStatus(ClockAndChallengeResultStatus.successful.getCode().byteValue());
            } else {
                result.setStatus(ClockAndChallengeResultStatus.failure.getCode().byteValue());
            }
            resultList.add(result);
        }
        pageInfo.setList(resultList);
        pageInfo.setPageSize(challengeRecordList.getPageSize());
        pageInfo.setPageIndex(challengeRecordList.getPageIndex());
        pageInfo.setTotal(challengeRecordList.getTotal());
        return pageInfo;
    }
}
